﻿using System;
using System.Timers;
using System.Windows.Input;
using YKXiangQi.Common;
using YKXiangQi.Enums;
using YKXiangQi.EventHandlers;
using YKXiangQi.Models;
using YKXiangQi.Utilities;

namespace YKXiangQi.ViewModels
{
    public class TimerControlViewModel: ViewModelBase
    {
        private Timer _timer;
        private IDialogService DialogService { get; set; }
        private Sides Turn { get; set; }

        public event TimeOutEventHandler TimeOut;
        
        public ICommand StartCommand { get; private set; }
        public ICommand PauseCommand { get; private set; }
        public ICommand ResetCommand { get; private set; }
        public ICommand OpenSettingsCommand { get; private set; }

        public TimerSettings Settings { get; set; }

        private bool _isRunning;
        public bool IsRunning
        {
            get { return _isRunning; }
            set
            {
                _isRunning = value;
                RaisePropertyChanged(() => IsRunning);
            }
        }

        public TimerControlViewModel()
        {
            DialogService = new DialogService();
            StartCommand = new RelayCommand(OnStart);
            PauseCommand = new RelayCommand(OnPause);
            ResetCommand = new RelayCommand(OnReset);
            OpenSettingsCommand = new RelayCommand(OnOpenSettings);
            Settings = TimerSettings.DefaultSettings;
            Turn = Sides.Red;
        }

        protected void OnStart(object param)
        {
            IsRunning = true;
            StartTimer();
        }

        protected void OnPause(object param)
        {
            StopTimer();
            IsRunning = false;
        }

        protected void OnReset(object param)
        {
            StopTimer();
            IsRunning = false;
            Settings = TimerSettings.DefaultSettings;
            Turn = Sides.Red;
            
            RaisePropertyChanged(() => RedPlayerTime);
            RaisePropertyChanged(() => BlackPlayerTime);
        }
        
        protected void OnOpenSettings(object param)
        {
            OnPause(param);

            var timerSettings = new TimerSettingsViewModel
                                    {
                                        Settings = this.Settings
                                    };
            var result = DialogService.ShowDialog(timerSettings);
            if (result != null && result.Value)
            {
                this.Settings = timerSettings.Settings;
                Turn = timerSettings.Settings.IsRedFirst ? Sides.Red : Sides.Black;

                RaisePropertyChanged(() => RedPlayerTime);
                RaisePropertyChanged(() => BlackPlayerTime);
                //RaisePropertyChanged(() => IncreaseTime);
                //RaisePropertyChanged(() => IncreasedTimeAmount);
            }
        }

        protected virtual void OnTimeOut(Sides side)
        {
            if (TimeOut != null)
                TimeOut(this, new TimeOutEventArgs(side));
        }

        private void StartTimer()
        {
            if(_timer == null)
            {
                _timer = new Timer(1000);
                _timer.Elapsed += TimerElapsed;
            }

            _timer.Start();
            TimerElapsed(this, null);//start timer immediately
        }

        private void StopTimer()
        {
            if (_timer != null)
                _timer.Stop();
        }

        private void TimerElapsed(object sender, ElapsedEventArgs e)
        {
            if(Turn == Sides.Red)
            {
                if (Settings.RedTotalTime <= 0)
                {
                    OnTimeOut(Sides.Red);
                    OnPause(null);
                    return;
                }

                Settings.RedTotalTime--;
                RaisePropertyChanged(() => RedPlayerTime);
            }
            else
            {
                if (Settings.BlackTotalTime <= 0)
                {
                    OnTimeOut(Sides.Black);
                    OnPause(null);
                    return;
                }

                Settings.BlackTotalTime--;
                RaisePropertyChanged(() => BlackPlayerTime);
            }
        }

        public string RedPlayerTime
        {
            get 
            {
                var time = TimeSpan.FromSeconds(Settings.RedTotalTime);
                return string.Format("{0:D2}:{1:D2}:{2:D2}", time.Hours, time.Minutes, time.Seconds);
            }
        }

        public string BlackPlayerTime
        {
            get
            {
                var time = TimeSpan.FromSeconds(Settings.BlackTotalTime);
                return string.Format("{0:D2}:{1:D2}:{2:D2}", time.Hours, time.Minutes, time.Seconds);
            }
        }

        public void Tick()
        {
           if(!IsRunning) 
               return;

            StopTimer();
            
            if (Settings.IsIncreaseTime)
            {
                if (Turn == Sides.Red)
                {
                    Settings.RedTotalTime += Settings.IncreasedTimeAmount;
                    RaisePropertyChanged(() => RedPlayerTime);
                }
                else
                {
                    Settings.BlackTotalTime += Settings.IncreasedTimeAmount;
                    RaisePropertyChanged(() => BlackPlayerTime);
                }
            }

            Turn = Turn == Sides.Red ? Sides.Black : Sides.Red;
            StartTimer();
        }
    }
}
